package timbap.visualizer.api.plugin.container;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import timbap.visualizer.api.exceptions.ReselectPlaylistException;
import timbap.visualizer.api.model.TimeCode;

import java.util.ArrayList;
import java.util.List;

/**
 * The <code>AbstractModeController</code> provides a common base
 * implementation for all mode controllers.
 *
 * @author  Andreas Pabst
 * @see     timbap.visualizer.api.plugin.container.ModeController
 * @see     timbap.visualizer.api.plugin.container.AbstractMixedPluginFork
 */
public abstract class AbstractModeController extends AbstractMixedPluginFork
                                             implements ModeController {
    
    private static final Log LOG = LogFactory.getLog(AbstractModeController.class);

    private TimeCode timeCode;
    private List<PluginSwitchCommandListener> pluginSwitchCommandListeners =
                            new ArrayList<PluginSwitchCommandListener>();

    private ModeController nextModeController;
    private ModeController previousModeController;

    private boolean flipSide = false;

    public ModeController getNextModeController() {
        return nextModeController;
    }

    public ModeController getPreviousModeController() {
        return previousModeController;
    }

    public void setNextModeController(final ModeController pNextModeController) {
        nextModeController = pNextModeController;
    }

    public void setPreviousModeController(final ModeController pPrevModeController) {
        previousModeController = pPrevModeController;
    }

    public void timeCodeUpdated(TimeCode pTimeCode) {
        if (timeCode == null) {
            flipSide = pTimeCode.isOnFlipSide();
        }
        this.timeCode = pTimeCode;
    }

    public void draw() {
        if (timeCode != null && (flipSide ^ timeCode.isOnFlipSide())) {
            LOG.warn("Vinyl has been flipped.");
            flipSide = !flipSide;
            if (getContext().getCfg().isReselectPlaylistWhenTurntableSwitchedOff()) {
                this.passivate();
                throw new ReselectPlaylistException();
            }
        }
        super.draw();
    }

    public void publishPluginSwitchCommand(PluginSwitchCommand pPluginSwitchCommand) {
        for (PluginSwitchCommandListener tListener: pluginSwitchCommandListeners) {
            tListener.handlePluginSwitchCommand(pPluginSwitchCommand);
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("published plugin switch command " + pPluginSwitchCommand + " from " + this);
        }
    }

    public void addPluginSwitchCommandListener(PluginSwitchCommandListener pListener) {
        pluginSwitchCommandListeners.add(pListener);
    }

    public void removePluginSwitchCommandListener(PluginSwitchCommandListener pListener) {
        pluginSwitchCommandListeners.remove(pListener);
    }

    public TimeCode getTimeCode() {
        return timeCode;
    }
    
}
